package com.csw.shuanfa.utils.id;

import com.csw.shuanfa.CodeImprove.redlockThread.redLockHand.RedisLock;
import com.csw.shuanfa.GlobalConfig.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Timer;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class NanoTimeUtil {
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private RedisLock redLock1;

    private String LOCK_KEY = "NanoTimeUtil";
    @Autowired
    private SnowFlakeIdUtil snowFlakeIdUtil;


    /**
     * 同一个机器上是单例【相当于上了一把锁一个一个进】，不同机器上分布式加锁或者用网卡地址区分
     * 红锁
     * 最近做压力测试，并发只弄到了 500 就报错了：org.springframework.data.redis.RedisSystemException: Unknown redis exception; nested exception is java.util.concurrent.RejectedExecutionException: Thread limit exceeded replacing blocked worker
     * <p>
     * springboot 中使用 redis 并发 500 时线程错误-鸿蒙开发者社区-51CTO.COM  https://ost.51cto.com/answer/6093
     * 一定要自定义线程池
     *
     * @return
     */
    public Long getNanoTimeId() throws Exception {
        RLock lock = redissonClient.getLock(LOCK_KEY);

        try {
            //500ms拿不到锁, 就认为获取锁失败。10000ms即10s是锁失效时间。
            boolean k = lock.tryLock(100, 1, TimeUnit.SECONDS);
            if (k) {
                String a = System.currentTimeMillis() + "";
                String b = System.nanoTime() + "";
                //最后两位不要，一般也取不到
                b = b.substring(b.length() - 6, b.length() - 2);
                String res = a + b;
                //休眠100纳秒,和去掉最后两位相照应
                TimeUnit.NANOSECONDS.sleep(100);
                return Long.valueOf(res);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

        throw new BusinessException("获取id失败");

    }

    /**
     * 最近做压力测试，并发只弄到了 500 就报错了：org.springframework.data.redis.RedisSystemException: Unknown redis exception; nested exception is java.util.concurrent.RejectedExecutionException: Thread limit exceeded replacing blocked worker
     * <p>
     * springboot 中使用 redis 并发 500 时线程错误-鸿蒙开发者社区-51CTO.COM  https://ost.51cto.com/answer/6093
     * 一定要自定义线程池
     *
     * @return
     */
    public Long getNanoTimeId2() throws Exception {
        String lockValue = UUID.randomUUID().toString();
        boolean locked = redLock1.tryAcquireLock(LOCK_KEY, lockValue, 100);
        if (locked == false) {
            throw new BusinessException("获取锁失败");
        }
        Timer timer = redLock1.getTimer(LOCK_KEY);

        try {
//            //500ms拿不到锁, 就认为获取锁失败。10000ms即10s是锁失效时间。
//
//            String a = System.currentTimeMillis() + "";
//            String b = System.nanoTime() + "";
//            //最后两位不要，一般也取不到
//            b = b.substring(b.length() - 6, b.length() - 2);
//            String res = a + b;
//            //休眠100纳秒,和去掉最后两位相照应
//            TimeUnit.NANOSECONDS.sleep(100);
//            return Long.valueOf(res);
            return 0L;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            redLock1.releaseLock(LOCK_KEY, lockValue);
            timer.cancel();
            //log.info("执行成功！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！{}" + new Date().toString() + LOCK_KEY);
        }

        throw new BusinessException("获取id失败");

    }


}
